package com.portal.sso.server.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.json.JSONUtil;
import com.portal.sso.core.config.PortalResault;
import com.portal.sso.core.config.SsoConfig;
import com.portal.sso.core.exception.WhitelistException;
import com.portal.sso.core.model.JwtModel;
import com.portal.sso.core.model.LineCaptchaModel;
import com.portal.sso.core.model.RequestModel;
import com.portal.sso.core.model.ResponseTModel;
import com.portal.sso.core.server.*;
import com.portal.sso.core.util.PortalSecureUtil;
import com.portal.sso.core.util.RequestHeaderTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Struct;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: portal-sso
 * @description: 登录页跳转
 * @author: xuduo
 * @create: 2021-04-17 12:10
 * @Version: 1.0
 **/
@Slf4j
@Controller
public class WebAppLoginController {
    @Autowired
    RequestServerHandler requestServerHandler;
    @Autowired
    TgtServerHander tgtServerHander;
    @Autowired
        JwtServerHander jwtServerHander;
    //    @Qualifier("portalSsoJdbcServer")
    @Autowired
    PortalUserServer portalUserServer;
    @Autowired
    AbstractTokenManage tokenManage;
    @Autowired
    VerificationCodeServer verificationCodeServer;

    @GetMapping(SsoConfig.SSO_LOGIN)
    public String LoginPage(Model model, HttpServletRequest request, HttpServletResponse response) {
        //1.判断cookie或者header的值是否存在
        //存在tgt并且合理则跳转到目标页
        RequestModel requestModel = requestServerHandler.LoadModel(request);
        //存在tgt则验证成功后跳转首页
        if (StrUtil.isNotEmpty(requestModel.getTgt())) {
            //开始验证tgt是否合法
            if (tgtServerHander.isExist(requestModel.getTgt())) {
                if (StrUtil.isNotEmpty(requestModel.getUrl())) {
                    Map<String, String> para = new HashMap<String, String>();
                    para.put(SsoConfig.SSO_COOKIE_TGT, requestModel.getTgt());
                    return "redirect:" + RequestHeaderTools.AddParaToUrl(requestModel.getUrl(), para, tokenManage.GetUriStyle(requestModel.getAppId()));
                } else {
                    return "redirect:/";
                }
            }
        }
        String uuid =IdUtil.simpleUUID();
        model.addAttribute("code_key_url", request.getContextPath()+"/code?code_key="+uuid);
        model.addAttribute("code_key",uuid);
        model.addAttribute("info", requestModel);
        //不存在直接展示登录页
        return "login";
    }

    @PostMapping(SsoConfig.SSO_LOGIN_ON)
    public String LoginForm(HttpServletRequest request, HttpServletResponse response) {

        RequestModel requestModel = requestServerHandler.LoadModel(request);
        if (StrUtil.isEmpty(requestModel.getTgt()) || tgtServerHander.getKey(requestModel.getTgt()) == null) {
            String userId = request.getParameter("username");
            String userPwd = request.getParameter("password");
            String userPwdKey = request.getParameter("password_key");
            String code_key = request.getParameter("code_key");
            String code = request.getParameter("code");
            if(StrUtil.isEmpty(code)){
                return "redirect:login";
            }
            if(!verificationCodeServer.verify(code_key,code)){

                return "redirect:login";
            }
            //解密数据
            String pwd_key = PortalSecureUtil.AesDecode(userPwdKey, null);
            String pwd_last = PortalSecureUtil.AesDecode(userPwd, pwd_key);



            if (portalUserServer.Verification(userId, pwd_last)) {
                String tgt = tokenManage.GenerateTgt(userId);
                tokenManage.SetCooket(response, tgt);
                response.setHeader(SsoConfig.SSO_HEADER_TGT, tgt);
                if (StrUtil.isEmpty(requestModel.getUrl())) {
                    return "redirect:/";
                } else {
                    Map<String, String> para = new HashMap<String, String>();
                    para.put(SsoConfig.SSO_COOKIE_TGT, tgt);
                    return "redirect:" + RequestHeaderTools.AddParaToUrl(requestModel.getUrl(), para, tokenManage.GetUriStyle(requestModel.getAppId()));
                }
            } else {
                return "redirect:login";
            }
        }
        return "index";
    }

    @RequestMapping({"", "/", "/index"})
    public String IndexPage(Model model, HttpServletRequest request, HttpServletResponse response) {
        RequestModel requestModel = requestServerHandler.LoadModel(request);
        log.debug(requestModel.toString());
        if (StrUtil.isNotEmpty(requestModel.getTgt())) {
            String tgt = requestModel.getTgt();
            String userId = tgtServerHander.getKey(tgt);
            log.debug(userId);
            model.addAttribute(SsoConfig.SSO_USER_ID, userId);

            return "index";
        } else {
            return "redirect:login";
        }

    }

    @PostMapping(SsoConfig.SSO_VERSION_URL)
    @ResponseBody
    public String LoginCheck(HttpServletRequest request, HttpServletResponse response) {
        RequestModel requestModel = requestServerHandler.LoadModel(request);

        if (StrUtil.isEmpty(requestModel.getAppId())) {
            return JSONUtil.toJsonStr(new ResponseTModel(PortalResault.NOT_APP_ID));
        }
        if (StrUtil.isEmpty(requestModel.getTgt())) {
            return JSONUtil.toJsonStr(new ResponseTModel(PortalResault.NOT_TGT));
        }
        //tgt存在
        String userId = tgtServerHander.getKey(requestModel.getTgt());
        if (StrUtil.isEmpty(userId)) {
            return JSONUtil.toJsonStr(new ResponseTModel(PortalResault.ERR_TGT_LICIT));
        }

        String server_ip = RequestHeaderTools.GetServerAndPort(request);
        //ip在白名单范围
        if (tokenManage.CheckAppId(requestModel.getAppId(), server_ip)) {
            //生成jwt并返回
            String jwt = null;
            try {
                jwt = tokenManage.GenerateToken(requestModel);
                JwtModel model = new JwtModel(jwt);
                //返回jwt
                return JSONUtil.toJsonStr(new ResponseTModel(model, PortalResault.OK.desc()));
            } catch (WhitelistException e) {
                log.error(e.getMessage(), e);
            }

        }

        //未正常生成时返回
        return JSONUtil.toJsonStr(new ResponseTModel(PortalResault.ERR_SSO_NOT_WHITELIST));
    }

    @GetMapping(SsoConfig.SSO_LOGOUT)
    public String Logout(Model model, HttpServletRequest request, HttpServletResponse response) {
        RequestModel requestModel = requestServerHandler.LoadModel(request);
        if (StrUtil.isEmpty(requestModel.getAppId())) {
            model.addAttribute(SsoConfig.SSO_REQUEST_ERROR_MSG, PortalResault.NOT_APP_ID.desc());
            return "error";
        }
        if (StrUtil.isEmpty(requestModel.getTgt())) {
            model.addAttribute(SsoConfig.SSO_REQUEST_ERROR_MSG, PortalResault.NOT_TGT.desc());
            return "error";
        }
        //检查tgt是否存在
        if (!tgtServerHander.isExist(requestModel.getTgt())) {
            model.addAttribute(SsoConfig.SSO_REQUEST_ERROR_MSG, PortalResault.ERR_TGT_LICIT.desc());
            return "error";
        }
        //ip在白名单范围
        String server_ip = RequestHeaderTools.GetServerAndPort(request);

        if (tokenManage.CheckAppId(requestModel.getAppId(), server_ip)) {
            //清除jwt并返回
            tokenManage.ClearUserId(response, requestModel.getTgt());
            return "redirect:login";
        }

        //未正常生成时返回
        model.addAttribute(SsoConfig.SSO_REQUEST_ERROR_MSG, PortalResault.ERR_SSO_NOT_WHITELIST.desc());
        return "error";
    }
    @GetMapping("/code")
    public void getCode(HttpServletRequest request, HttpServletResponse response,String code_key) throws IOException {
        if(StrUtil.isNotEmpty(code_key)){
            LineCaptchaModel lineCaptchaModel = verificationCodeServer.createCaptcha(100,50,code_key);
            lineCaptchaModel.getCaptcha().write(response.getOutputStream());
        }

    }
}
